/**
 * Copyright (C) 2017-2018 pinganfang, Inc. All Rights Reserved.
 */
package com.pingan.haofang.searchcloud.register.route;

import com.google.common.collect.Maps;
import com.pingan.haofang.searchcloud.api.matedata.MetaCacheSupport;
import com.pingan.haofang.searchcloud.api.route.IndexAliasRegister;
import com.pingan.haofang.searchcloud.api.route.IndexRoute;
import com.pingan.haofang.searchcloud.api.route.IndexRouteRegister;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.Collections;
import java.util.Map;

/**
 * @author huhailiang937
 * @date 2017年7月6日上午11:27:38
 * @since 1.0.0
 */
@Service("redisIndexRouteRegister")
@ManagedResource
public class RedisIndexRouteRegister implements IndexRouteRegister {

    protected static Logger LOG = LoggerFactory.getLogger(RedisIndexRouteRegister.class);

    private static RedisTemplate redisTemplate;

    private static Map<String, IndexAliasRegister> map;

    // JDK ServiceLoader 初始化需无参构造器
    public RedisIndexRouteRegister() {
        LOG.info("-----> JDK ServiceLoader  IndexRouteRegister for redisIndexRouteRegister init sucess");
    }

    @Autowired
    public RedisIndexRouteRegister(ApplicationContext applicationContext) {

        redisTemplate = (RedisTemplate) applicationContext.getBean("redisQueueTemplate");
        if(redisTemplate == null ){
            LOG.error("RedisIndexRouteRegister init error ,can not found redisTemplate");
            throw new RuntimeException("RedisIndexRouteRegister init error ,can not found redisTemplate");
        }

        map = applicationContext.getBeansOfType(IndexAliasRegister.class);
        map = (null == map) ? Maps.newHashMap() : map;
        LOG.info("---> Spring loader IndexRouteRegister for  redisIndexRouteRegister init sucess");
    }

    @Override
    public IndexRoute discover(String collectionRouteKey) {
        Assert.notNull(collectionRouteKey, "collectionRouteKey can not null");
        String json = (String) redisTemplate.opsForHash().get(MetaCacheSupport.ROOT_ROUTE_KEY, collectionRouteKey);
        if (null == json) {
            return null;
        }
        try {
            IndexRoute routeInZk = MetaCacheSupport.decode4Json(json, IndexRoute.class);
            if (null != routeInZk.getEndpoints()) {
                Collections.sort(routeInZk.getEndpoints());
            }
            return routeInZk;
        } catch (Exception e) {
            LOG.error(String.format("redisCollectionRouteDiscover discover(%s) has error: ", collectionRouteKey), e);
            return null;
        }
    }

    @Override
    public boolean register(IndexRoute indexRoute) {
        Assert.notNull(indexRoute, "collectionRoute can not null");
        Assert.notNull(indexRoute.getCollectionRouteKey(), "CollectionRouteKey can not null");
        Assert.notNull(indexRoute.getCollectionName(), "CollectionName can not null");
        String json = null;
        try {
            json = new String(MetaCacheSupport.encode(indexRoute));
            redisTemplate.opsForHash().put(MetaCacheSupport.ROOT_ROUTE_KEY, indexRoute.getCollectionRouteKey(), json);
            LOG.info(String.format("redisCollectionRouteRegister register CollectionRoute : %s", json));

            if (CollectionUtils.isNotEmpty(map.values())) {
                for (IndexAliasRegister aliasRegister : map.values()) {
                    aliasRegister.register(indexRoute);
                }
            }
            return true;
        } catch (Exception e) {
            LOG.error(String.format("redisCollectionRouteRegister register fail! setData(%s) has error:", json), e);
        }
        return false;
    }

}
